package evo;

import java.util.ArrayList;
import java.util.List;

import app.Board;

import net.lab0.tools.StaticRandom;
import net.lab0.tools.evo.iface.Individual;

public class Type1Solution
implements Individual<Type1Solution>
{
    private boolean[] genome;
    private double    fitness;
    private Board     board;
    
    public Type1Solution(Board board, int maxSize)
    {
        int size = StaticRandom.random.nextInt(maxSize);
        this.genome = new boolean[size];
        for (int i = 0; i < size; ++i)
        {
            genome[i] = StaticRandom.random.nextBoolean();
        }
        this.board = board;
        computeFitnes();
    }
    
    public Type1Solution(Board board, boolean[] genome)
    {
        this.genome = genome;
        this.board = board;
        computeFitnes();
    }
    
    public void mutate()
    {
        int i = StaticRandom.random.nextInt(genome.length);
        genome[i] = !genome[i];
        computeFitnes();
    }
    
    @Override
    public List<Type1Solution> cross(Type1Solution other)
    {
        Type1Solution individual = (Type1Solution) other;
        int i1 = StaticRandom.random.nextInt(genome.length);
        int i2 = StaticRandom.random.nextInt(individual.genome.length);
        
        boolean[] newGenome1 = new boolean[i1 + individual.genome.length - i2 + 1];
        boolean[] newGenome2 = new boolean[i1 + individual.genome.length - i2 + 1];
        
        for (int i = 0; i <= i1; ++i)
        {
            newGenome1[i] = this.genome[i];
            newGenome2[i] = individual.genome[i];
        }
        for (int i = i2; i <= individual.genome.length; ++i)
        {
            newGenome1[i1 + i] = individual.genome[i];
            newGenome2[i1 + i] = this.genome[i];
        }
        
        List<Type1Solution> ret = new ArrayList<>(2);
        ret.add(new Type1Solution(this.board, newGenome1));
        ret.add(new Type1Solution(this.board, newGenome2));
        
        return ret;
    }
    
    @Override
    public double getFitness()
    {
        return fitness;
    }
    
    private void computeFitnes()
    {
        Board clone = new Board(board);
        clone.execute(genome);
        fitness = 0.0;
    }
}
